﻿
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using BearUtil.Hidden;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEngine;
using XNode;
using XNodeEditor;

namespace BearUtil
{
    /// <summary>
    /// 剧情片段
    /// </summary>
    [NodeGraphEditor.CustomNodeGraphEditorAttribute(typeof(StoryGraph))]
    [Serializable, CreateAssetMenu(fileName = "NewStory", menuName = "Story&Dialog/Create Story"), 
     RequireNode(typeof(StartNode), typeof(EndNode))]
    public class StoryGraph : XNode.NodeGraph, ICustomSetting, ICustomGraph
    {
        [BoxGroup("基本属性"), HideLabel] public BasicProperty basic;
#region Setting
        public string AddName 
        {
            get {  return "导出 Excel"; }
            set { }
        }

        public string RemoveName
        {
            get {  return "删除 Excel"; }
            set { }
        }
        
        [HideInInspector, SerializeField]
        public int genCount = 0;

        // 编辑器上一次停留位置
        [HideInInspector]
        public Vector2 LastFocusPosition;
        
        /// <summary>
        /// 导出 Excel 数据
        /// </summary>
        /// <param name="window"></param>
        public void Add(OdinMenuEditorWindow window)
        {
            // 全部 dialog 遍历
        }

        /// <summary>
        /// 删除 Excel 数据
        /// </summary>
        /// <param name="selected"></param>
        public void Remove(OdinMenuItem selected)
        {
            // 移除全部 excel
        }
#endregion

        public StoryGraph()
        {
            if (basic == null)
                basic = new BasicProperty();

            if (basic.audioData.SyncFontSpeedCallback == null)
                basic.audioData.SyncFontSpeedCallback = SyncFontSpeed;
        }

        public void UpdateData()
        {
            // reset node index
            for (int i = 0; i < nodes.Count(); i++)
            {
                var bn = (nodes[i] as BearNode);
                if (bn == null)
                {
                    continue;
                }
                
                bn.index = i + 1;
            }
        }

        /// <summary>
        /// 添加接点时
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public override Node AddNode(Type type)
        {
            Node node = null;
            genCount++;
            // 设置 index
            switch (type.Name)
            {
                case "DialogNode":
                    node = base.AddNode(type);
                    DialogNode bn = (node as DialogNode);
                    if (bn == null)
                        return node;
            
                    bn.id = genCount;
                    bn.name = name + "_" +type.Name + "_" + genCount.ToString();
                    basic.Clone(ref bn.basic);
                    // 设置 scriptObject 关联
                    bn.BindGraph(GenerateScriptObject(bn) as DialogGraph);
                    break;
                default:
                    node = base.AddNode(type);
                    break;
            }

            UpdateData();
            
            return node;
        }

        public override Node CopyNode(Node original)
        {
            genCount++;
            Node node = null;
            var type = original.GetType();
            switch (type.Name)
            {
                case "DialogNode":
                    node = base.CopyNode(original);
                    DialogNode bn = (node as DialogNode);
                    if (bn == null)
                        return node;
            
                    bn.id = genCount;
                    bn.name = name + "_" + genCount.ToString();
                    basic.Clone(ref bn.basic);
                    // 设置 scriptObject 关联
                    bn.BindGraph(GenerateScriptObject(bn) as DialogGraph);
                    break;
                default:
                    node = base.CopyNode(original);
                    break;
            }

            UpdateData();
            
            return node;
        }

        public override void RemoveNode(Node node)
        {
            base.RemoveNode(node);
            UpdateData();
        }

        /// <summary>
        /// 创建 dialog 需要的 graph
        /// </summary>
        private const string dialogPath = "Assets/StoryEditor/Nodes/Dialogs/Data/";
        private ScriptableObject GenerateScriptObject(BearNode node)
        {
            StringBuilder sb = new StringBuilder(dialogPath);
            sb.Append(name);
            sb.Append("/");

            string dir = sb.ToString();
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
                AssetDatabase.Refresh();
            }
            
            sb.Append(node.name);
            sb.Append("_graph.asset");
            Type dgType = typeof(DialogGraph);
            var graph = ScriptableObject.CreateInstance(dgType);
            
            string path = sb.ToString();
            var asset = AssetDatabase.LoadAssetAtPath(path, dgType);
            if (asset != null)
                AssetDatabase.DeleteAsset(path);
            
            AssetDatabase.CreateAsset(graph, path);
            AssetDatabase.Refresh();

            return graph;
        }

        private void SyncFontSpeed()
        {
            for (var i = 0;  i < nodes.Count; i++)
            {
                var node = nodes[i] as DialogNode;
                if (node == null)
                    continue;

                node.basic.audioData.FontSpeed = basic.audioData.FontSpeed;
                node.SyncFontSpeed();
            }
        }

        /// <summary>
        /// 输出数据
        /// </summary>
        [Button("输出 Story 章节数据", ButtonSizes.Large)]
        public void OutputData()
        {
            List<StoryDataFormat> sdfs = new List<StoryDataFormat>();
            for (int i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];
                var dn = node as DialogNode;
                if (dn)
                {
                    var sd = new StoryDataFormat();
                    sdfs.Add(sd);
                    // s_ 适应 lua table 明明需求
                    sd.index = $"s_{basic.id}_{(i >= 2 ? i - 1 : i)}";
                    sd.SetDialog(dn, sdfs.Count);
                }
                else
                {
                    if (!node.GetType().Name.Contains("StartNode") && !node.GetType().Name.Contains("EndNode"))
                        Debug.LogError("Error DialogNode Data:" + nodes[i].name);
                }
            }

            UpdateData();

            var excelData = ExcelDataGenerator.GenerateExcelData<StoryDataFormat>(sdfs);
            if (excelData == null)
                return;
            
            excelData.sheetName = name;
            Utils.CreateScriptableObject(excelData, ExcelDataGenerator.Instance.StoriesDataPath, name);

            string foldPath = ExcelDataGenerator.Instance.OutputExcelFold + "/" + "章节";
            ExcelEdit.WriteExcel(excelData, foldPath);
        }

        [Button("输出 Dialog 节点内数据", ButtonSizes.Large)]
        public void GenerateDialogData()
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];
                var dn = node as DialogNode;
                if (dn && dn.DialogGraph != null)
                {
                    dn.DialogGraph.OutputData();
                }
            }
        }
        
        //
        // /// <summary>
        // /// 旧数据兼容到新数据
        // /// </summary>
        // [Button("覆盖兼容数据", ButtonSizes.Large)]
        // public void CoverData()
        // {
        //     for (int i = 0; i < nodes.Count; i++)
        //     {
        //         var node = nodes[i];
        //         var dn = node as DialogNode;
        //         if (dn && dn.DialogGraph != null)
        //         {
        //             dn.Transform();
        //
        //             dn.DialogGraph.CoverDataToOld();
        //             EditorUtility.SetDirty(dn.DialogGraph);
        //             AssetDatabase.Refresh();
        //         }
        //     }
        // }
    }
}

